"""
Algoritmo del script

# 1 cargar los archivos
# 2     iterar las muestras
# 3         para cada muestra iterar las secuencias
# 4             para cada secuencia obtener las que cumplen con el valor de aceptacion
# 5         buscar si la secuencia esta en la base de datos
# 6         busca en la base de datos las secuencisas que identifican más de una especie o familia
# 7     elimina todas las columnas que no tienen ni una sola coincidencia
# 8     elimina todas las filas que no tienen ni una sola coincidencia
# 9     llena todos los espacios vacios con ceros
# 10    Agrega una fila de totales
# 11    Ordeno las familias o especies de la que tiene más coincidencias a la que menos tiene
# 12    Caculo cuantos peptidos coinciden para cada columna
# 13    Agrego una columna de total de coincidencias
# 14    Elimino los peptidos que no coinciden con ninguna familia
# 15    Calculo la cantidad de peptidos unicos para cada familia
# 16    Imprimo el archivo

"""

"""
Librerias a utilizar
"""
import pandas as pd  # Libreria para cargar y manipular los datos || Esta libreria debe ser instalada con el comando pip install pandas

# TODO crear posibles metodos para mandar a llamar

"""
Configuración del script
"""
# fmt: off

# Configuración del archivo de muestras
nombreArchivoMuestras = "Multiconsensus_AN1-98_filtered.csv"  # Nombre del archivo de muestras
nombreColumnaIndiceMuestras = "Sequence"  # Nombre de la columna que identifica cada fila

# Configuración del archivo de base de datos
nombreArchivoBD = "Peptide_lookup_species_63.csv" # Nombre del archivo de base de datos
nombreColumnaIndiceBD = "peptide"  # Nombre de la columna que identifica cada fila

# Configuraciones generales
valorDeAceptación = 0  # Valor que deben tener las muestras para ser tomadas en cuenta
eliminarColumnasSinCoincidencias = True # Elimina las especies que no coincidieron con ningun peptido
eliminarFilasSinCoincidencias = True # Elimina los peptidos que no coincidieron con ninguna especie
agregarFilaTotales = True  # Agrega una fila de totales
agregarColumnaTotales = True  # Agrega una columna de totales
eliminaPeptidosSinCoincidencias = False # Elimna los peptidos que coinciden con una sola familia
eliminarColumnasConPocasCoincidencias = True # Deletes columns with less than 50% of the column with more peptides
calcularPeptidosUnicos = True # Elimina las familias que tienen uno o ningun peptido único

# fmt: on
"""
Preparación de los datos y las variables a utilizar
"""
# Lectura y carga de las muestras
data = pd.read_csv(
    nombreArchivoMuestras, delimiter=";", index_col=nombreColumnaIndiceMuestras
)

# Lectura y carga de la base de datos
base = pd.read_csv(nombreArchivoBD, delimiter=";", index_col=nombreColumnaIndiceBD)

listaMuestras = data.columns  # Listado de muestras
numeroMuestras = data.shape[1]  # Obtengo el número de columnas
numeroColumnas = base.shape[1]  # Obtengo el número de columnas
listaOrdenes = base.columns  # Listado de ordenes
muestraActual = 1  # Variable para hacer ciclos por muestra

"""
Proceso de los datos
"""
# ciclo para iterar todas las muestras
while muestraActual < numeroMuestras:

    print("> Inicio de la muestra " + listaMuestras[muestraActual - 1])

    # Lista donde guardaremos las secuencias que tengan high en la muestra actual
    secuencias = []

    # estructura donde guardaremos los datos
    salida = pd.DataFrame(columns=base.columns, index=data.index)

    # Ciclo para iterar todas las secuencias
    for row in data.itertuples():
        # Valida que el valor de la muestra sea 3
        if row[muestraActual] > valorDeAceptación:
            # Añade la secuencia a la lista
            # row en la posición 0 tiene la secuencia, en las demas posiciones tiene el valor de la muestra
            secuencias.append(row[0])

    # ciclo para iterar las secuencias de la muestra actual
    for secuencia in secuencias:

        # Verifica si la secuencia esta en la base de datos
        if secuencia in base.index:
            # Guardo la secuencia
            secuenciaTemporal = base.loc[secuencia]

            # Ciclo para iterar todos los ordenes o familias
            for i in range(0, numeroColumnas - 1):

                # Valida que la secuencia identifique más de uno
                if secuenciaTemporal[i] > 0:
                    # Guarda los datos en un formato un poco loco para que quede en csv
                    salida.at[secuencia, listaOrdenes[i]] = 1
        else:
            # Imprime que no encontro la muestra en la base de datos
            print("\tLa secuencia " + secuencia + " no fue encontrada")

    # Limpia las columnas que no tienen ni una coincidencia
    if eliminarColumnasSinCoincidencias:
        salida = salida.dropna(axis="columns", how="all")

    # Limpia las filas que no tienen ni una coincidencia
    if eliminarFilasSinCoincidencias:
        salida = salida.dropna(axis="index", how="all")

    # Rellena de ceros los espacios en blanco
    salida = salida.fillna(0)

    # Agrego una columna con el recuento de secuencias que hicieron match
    if agregarFilaTotales:
        salida.loc["Total"] = salida.sum()

        # Ordeno las columnas de la que más match tiene
        salida = salida.sort_values(by="Total", axis=1, ascending=False)

    if agregarColumnaTotales:
        # Suma la cantidad de peptidos cada secuencia
        totalesColumnas = salida.sum(axis=1, numeric_only=True)

        # Agrego la nueva columna a la estructura de datos
        salida.insert(0, "Total_Coincidencias", totalesColumnas, True)

    if eliminaPeptidosSinCoincidencias:

        filasPorEliminar = []  # Listado de nombres de columnas a eliminar

        # Elimino los peptidos que no coinciden con ninguna familia/orden
        for index, fila in salida.iterrows():
            if listaMuestras[muestraActual - 1] == "AN477":
                print(index)
                print(fila)
                print(salida.at[index, "Total_Coincidencias"])
            if salida.at[index, "Total_Coincidencias"] == 0:
                filasPorEliminar.append(index)

        salida = salida.drop(list(dict.fromkeys(filasPorEliminar)), axis="rows")

    if eliminarColumnasConPocasCoincidencias:
        secuencias = salida.index  # Obtengo un listado se secuencias

        columnasPorEliminar = []  # Listado de nombres de columnas a eliminar

        # Calcula la mitad de peptidos de la familia que más tiene
        reglaDel50 = salida.at["Total", salida.columns[1]] / 2

        # Ciclo para iterar todas las columnas
        for columna in salida.columns:
            # Si es menor a la mitad del que más tiene se eliminan
            if salida.at["Total", columna] < reglaDel50:
                # Añade a la lista de columnas por eliminar
                columnasPorEliminar.append(columna)

        # Elimina las columnas
        salida = salida.drop(list(dict.fromkeys(columnasPorEliminar)), axis="columns")

    if agregarColumnaTotales:

        # Deletes column to replace it
        salida = salida.drop("Total_Coincidencias", axis="columns")

        # Suma la cantidad de peptidos cada secuencia
        totalesColumnas = salida.sum(axis=1, numeric_only=True)

        # Agrego la nueva columna a la estructura de datos
        salida.insert(0, "Total_Coincidencias", totalesColumnas, True)

    if eliminaPeptidosSinCoincidencias:

        filasPorEliminar = []  # Listado de nombres de columnas a eliminar

        # Elimino los peptidos que no coinciden con ninguna familia/orden
        for index, fila in salida.iterrows():
            if listaMuestras[muestraActual - 1] == "AN477":
                print(index)
                print(fila)
                print(salida.at[index, "Total_Coincidencias"])
            if salida.at[index, "Total_Coincidencias"] == 0:
                filasPorEliminar.append(index)

        salida = salida.drop(list(dict.fromkeys(filasPorEliminar)), axis="rows")

    # Elimina familias u ordenes con uno o menos peptidos
    if calcularPeptidosUnicos:
        salida.loc["Total_Peptidos_Unicos"] = 0

        # Calcula el total de peptidos unicos para cada familia/orden
        for index, row in salida.iterrows():
            if row["Total_Coincidencias"] == 1:
                for column in salida:
                    if salida.at[index, column] == 1:
                        salida.at["Total_Peptidos_Unicos", column] += 1

    # Imprime el archivo salida.csv
    salida.to_csv(
        "Output 1 - " + listaMuestras[muestraActual - 1] + ".csv",
        index=True,
        header=True,
    )

    # Imprime que ya termino de procesar la muestra
    print("< Fin de la muestra " + listaMuestras[muestraActual - 1] + "\n")

    # pasa a la siguiente muestra
    muestraActual += 1
